package com.maezia.tdr.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maezia.tdr.common.CommonConstant;
import com.maezia.tdr.common.LockProvider;
import com.maezia.tdr.common.enums.StatusCodeEnum;
import com.maezia.tdr.common.exception.DriveException;
import com.maezia.tdr.common.exception.TooManyException;
import com.maezia.tdr.dao.mapper.TestDriveReportMapper;
import com.maezia.tdr.dao.repository.ReportRepository;
import com.maezia.tdr.dao.repository.TestDriveReportRepository;
import com.maezia.tdr.domain.dto.ReportInfoDto;
import com.maezia.tdr.domain.po.Dict;
import com.maezia.tdr.domain.po.TestDriveReport;
import com.maezia.tdr.domain.vo.ReportVo;
import com.maezia.tdr.service.DictService;
import com.maezia.tdr.service.ReportService;
import com.maezia.tdr.utils.MD5Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class ReportServiceImpl extends ServiceImpl<TestDriveReportMapper, TestDriveReport> implements ReportService {

    @Autowired
    private ReportRepository reportRepository;

    @Autowired
    private LockProvider lockProvider;

    @Autowired
    private DictService dictService;

    @Autowired
    private TestDriveReportMapper testDriveReportMapper;

    @Autowired
    private TestDriveReportRepository testDriveReportRepository;

    @Override
    public TestDriveReport getByMd5(String md5) {
        return testDriveReportMapper.getByMd5(md5);
    }

    @Override
    public ReportVo getReportInfo(ReportInfoDto reportInfo) throws TooManyException, DriveException {
        Date startTime = DateUtil.parse(reportInfo.getStartTime(), CommonConstant.UTC_DATE_TIME_FORMAT);
        Date endTime = DateUtil.parse(reportInfo.getEndTime(), CommonConstant.UTC_DATE_TIME_FORMAT);
        if(startTime.after(endTime)){
            throw new DriveException(StatusCodeEnum.INVALID_TIME_RANGE);
        }

        if("false".equals(reportInfo.getConsentState())){
            return null;
        }

        String key = CommonConstant.GET_REPORT_INFO + CommonConstant.COLON + reportInfo.getVehicleId();
        Dict dict = dictService.getByKey(CommonConstant.GET_REPORT_INFO);
        boolean isLock = lockProvider.lock(key, reportInfo.getVehicleId(), Long.valueOf(dict.getValue()), TimeUnit.MINUTES);
        if(!isLock){
            throw new TooManyException(StatusCodeEnum.TOO_MANY_REQUEST);
        }

        String linkValue = reportInfo.getVehicleId() + "_" + startTime + "_" + endTime;
        String md5 = MD5Utils.getMD5(linkValue);
        String taskRedisKey = CommonConstant.REPORT_TASK_EXE_TIME + CommonConstant.COLON + md5;
        dict = dictService.getByKey(CommonConstant.REPORT_TASK_EXE_TIME);
        boolean isLockTask = lockProvider.lock(taskRedisKey, linkValue, Long.valueOf(dict.getValue()), TimeUnit.MINUTES);
        if(isLockTask){
            reportRepository.sendMessage(reportInfo);
        }
        return reportRepository.getReportVo(md5);
    }

    @Override
    public void refreshReportCache(TestDriveReport report) {
        reportRepository.refreshReportCache(report) ;
    }

    @Override
    public ReportVo getReportVo(String md5) {
        return reportRepository.getReportVo(md5);
    }

    @Override
    public boolean isReportExpired(String md5) {
        TestDriveReport report = testDriveReportRepository.getByMd5(md5);
        if(ObjectUtils.isEmpty(report)){
            return true;
        }

        return new Date().after(report.getCreateTime());
    }
}
